11.05.2020

https://leetcode.com/problems/3sum

How to solve

Iterate through the first N - 2 numbers, fixing each number as a possible first number in our triplet. At each iteration, we use two pointers, lo and hi. We initialize lo to point to the first number after i, and hi to point to the last number. Move both pointers inwards until you find two numbers that when summed with i, make a valid triplet.

Complexity Analysis

Time: O(N2)

The outer for loop runs at least N - 2 times. In the worst case, the inner for-loop will have to run O(N) times.

Space: O(log N)

nums.sort() uses log N space for function calls.

Solutions

Python

def threeSum(self, nums: List[int]) -> List[List[int]]:
    nums.sort()
    ans = []

    for i in range(len(nums) - 2):
        if nums[i] > 0:
            return ans
        if i > 0 and nums[i - 1] == nums[i]:
            continue

        l = i + 1
        r = len(nums) - 1

        while l < r:
            sum_triple = nums[i] + nums[l] + nums[r]

            if sum_triple > 0:
                r -= 1
            elif sum_triple < 0:
                l += 1
            else:
                ans.append([nums[i], nums[l], nums[r]])
                while l < r and nums[l] == nums[l + 1]:
                    l += 1
                while l < r and nums[r - 1] == nums[r]:
                    r -= 1
                l += 1
                r -= 1

    return ans

Go

import "sort"

func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    ans := make([][]int, 0)

    for i := 0; i < len(nums) - 2; i++ {
        if nums[i] > 0 {
            return ans
        } else if (i > 0) && (nums[i - 1] == nums[i]) {
            continue
        }

        l := i + 1
        r := len(nums) - 1

        for l < r {
            sum_triple := nums[i] + nums[l] + nums[r]

            if sum_triple < 0 {
                l += 1
            } else if sum_triple > 0 {
                r -= 1
            } else {
                ans = append(ans, []int{nums[i], nums[l], nums[r]})

                for (l < r) && (nums[l] == nums[l + 1]) {
                    l += 1
                }
                for (l < r) && (nums[r] == nums[r - 1]) {
                    r -= 1
                }
                l += 1
                r -= 1
            }
        }
    }
    return ans

Rust

    pub fn three_sum(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
        if nums.len() < 3 {
            return Vec::<Vec<i32>>::new();
        }
        nums.sort();
        let mut ans: Vec<Vec<i32>> = Vec::new();

        for i in 0..nums.len() - 2 {
            if nums[i] > 0 {
                return ans;
            } else if (i > 0) && (nums[i - 1] == nums[i]) {
                continue;
            }

            let mut l = i + 1;
            let mut r = nums.len() - 1;

            while l < r {
                let mut sum_triple = nums[i] + nums[l] + nums[r];

                if sum_triple < 0 {
                    l += 1;
                } else if sum_triple > 0 {
                    r -= 1;
                } else {
                    ans.push(vec![nums[i], nums[l], nums[r]]);

                    while (l < r) && (nums[l] == nums[l + 1]) {
                        l += 1;
                    }
                    while (l < r) && (nums[r] == nums[r - 1]) {
                        r -= 1;
                    }
                    l += 1;
                    r -= 1;
                }
            }
       }
        ans
    }
}